package kr.pe.silent.etweeter;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Map;

/**
 * @author Sanghoon Lee
 * $Id: ETweeter.java 20 2011-11-15 05:09:37Z calm1979 $
 *
 */
public class ETweeter {

	public static final String OAuthConsumerKey = "OAuthConsumerKey";
	public static final String OAuthConsumerSecret = "OAuthConsumerSecret";
	
	private static final String AccessTokenKey = "AccessTokenKey";
	private static final String AccessTokenSecretKey = "AccessTokenSecretKey";
	
	private static final String UsernameIdKey = "UsErNaMeIdS";
	private static final String UsernameIdSeperater = ":";
	
	private static final String EMPTY_STRING = "";
	
	private static final Map<String, Long> mapUsernameId = new Hashtable<String, Long>();
	static {
		IPreferenceStore preferenceStore = ETweeterPlugin.getDefault().getPreferenceStore();
		String usernameIdValue = preferenceStore.getString(UsernameIdKey);
		if (!EMPTY_STRING.equals(usernameIdValue)) {
			// screenname1|userid1|screenname2|userid2|...
			String[] usernameIds = usernameIdValue.split(UsernameIdSeperater);
			for (int i = 0; i < usernameIds.length; ) {
				String username = usernameIds[i++];
				String userId = usernameIds[i++];
				try {
					mapUsernameId.put(username, Long.valueOf(userId));
				} catch (NumberFormatException e) {
				}
			}
		}
	}
	
	private static Twitter twitter;
	private static RequestToken requestToken;

	/**
	 * @return username array
	 */
	public static String[] getUsernames() {
		return (String[])mapUsernameId.keySet().toArray(new String[mapUsernameId.size()]);
	}
	
	/**
	 * @param username
	 * @return username's userId
	 */
	public static long getUserId(String username) {
	    Long userId = mapUsernameId.get(username); 
		return userId == null ? 0 : userId;
	}
	
	/**
	 * Twitter for userId. If return value is null, then use {@link openOAuthBrowser()}.
	 * @param userId
	 * @return Twitter (or null)
	 */
	public static Twitter getTwitter(long userId) {
		twitter = new TwitterFactory().getInstance();
		twitter.setOAuthConsumer(ETweeter.OAuthConsumerKey, ETweeter.OAuthConsumerSecret);
		AccessToken accessToken = loadAccessToken(userId);
		if (accessToken == null) {
			return null;
		}
		twitter.setOAuthAccessToken(accessToken);

		return twitter;
	}

	/**
	 * Open browser for get PIN.
	 */
	public static void openOAuthBrowser() {
		try {
			requestToken = twitter.getOAuthRequestToken();

			IWorkbenchBrowserSupport support = PlatformUI.getWorkbench()
					.getBrowserSupport();
			IWebBrowser browser = support.createBrowser(null);
			browser.openURL(new URL(requestToken.getAuthorizationURL()));
		} catch (PartInitException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (TwitterException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * This method use after {@link openOAuthBrowser()} call.
	 * In this method, save AccessToken, too.
	 * @param pin
	 * @return
	 */
	public static Twitter getTwitter(String pin) {
		try {
			AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, pin);
			saveAccessToken(accessToken);
			
			saveUserInfo(accessToken);
			return twitter;
		} catch (TwitterException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private static void saveUserInfo(AccessToken accessToken) {
	    Long userId = mapUsernameId.get(accessToken.getScreenName());
		if (userId == null) {
			mapUsernameId.put(accessToken.getScreenName(), accessToken.getUserId());
			
			IPreferenceStore preferenceStore = ETweeterPlugin.getDefault().getPreferenceStore();
			String usernameIdValue = preferenceStore.getString(UsernameIdKey);
			if (!EMPTY_STRING.equals(usernameIdValue)) {
				usernameIdValue += UsernameIdSeperater;
			}
			usernameIdValue += (accessToken.getScreenName() + UsernameIdSeperater + accessToken.getUserId());
			preferenceStore.setValue(UsernameIdKey, usernameIdValue);
		}
	}

	private static void saveAccessToken(AccessToken accessToken) {
		IPreferenceStore preferenceStore = ETweeterPlugin.getDefault().getPreferenceStore();
		preferenceStore.setValue(AccessTokenKey + accessToken.getUserId(), accessToken.getToken());
		preferenceStore.setValue(AccessTokenSecretKey + accessToken.getUserId(), accessToken.getTokenSecret());
	}

	private static AccessToken loadAccessToken(long userId) {
		IPreferenceStore preferenceStore = ETweeterPlugin.getDefault().getPreferenceStore();
		String accessToken = preferenceStore.getString(AccessTokenKey + userId);
		String accessTokenSecret = preferenceStore.getString(AccessTokenSecretKey + userId);
		if (EMPTY_STRING.equals(accessToken) || EMPTY_STRING.equals(accessTokenSecret))
			return null;
		return new AccessToken(accessToken, accessTokenSecret);
	}
}
